package cn.rui.aspects;

import cn.dev33.satoken.exception.NotLoginException;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.system.SystemUtil;
import cn.rui.pojo.ErrorLog;
import cn.rui.pojo.OperationLog;
import cn.rui.pojo.User;
import cn.rui.service.ErrorLogService;
import cn.rui.service.OperationLogService;
import cn.rui.service.UserService;
import cn.rui.utils.IpUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;

/**
 * 切面类,启动类上加  @EnableAspectJAutoProxy注解
 * @author 徽州大都督
 * @date 2020/8/14
 */
@Aspect
@Component
public class MyAspects {

    @Autowired
    private OperationLogService operationLogService;

    @Autowired
    private UserService userService;

    @Autowired
    private ErrorLogService errorLogService;

    //日志
    private static Logger logger = LoggerFactory.getLogger (MyAspects.class);

    //定义切入点在controller下面的所有类所有方法任意参数
    @Pointcut("execution(* cn.rui.controller.*.*(..))")
    public void weblog(){

    }

    //前置通知
    @Before ("weblog()")
    public void myBefore(JoinPoint joinPoint) throws NoSuchMethodException {

        Object target = joinPoint.getTarget();
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = target.getClass().getMethod(signature.getName(), signature.getParameterTypes());

        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes ();
        ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) requestAttributes;

        HttpServletRequest request = servletRequestAttributes.getRequest ();

        //获取security保存的用户信息
        //Authentication authentication = SecurityContextHolder.getContext().getAuthentication();

        //当前登录用户
        //logger.info ("username:{}",request.getSession().getAttribute("username"));
        Log annotation = method.getAnnotation(Log.class);
        if (annotation!=null){
            //controll层@Log注解的内容
            //logger.info ("content:{}",annotation.value ());
            OperationLog operationLog = new OperationLog ();
            operationLog.setAddress (IpUtils.getIpAdrress (request));
            operationLog.setContent (annotation.value ());
            operationLog.setIp4Host (SystemUtil.getHostInfo ().getAddress ());

            String uuid = StpUtil.getLoginIdAsString ();
            User user = userService.findUserNameByUUid (uuid);
            operationLog.setLoginName (user.getUsername ());
            operationLog.setUrl (request.getRequestURI ());
            operationLog.setOperationSystem (SystemUtil.getOsInfo ().getName ());
            operationLogService.save(operationLog);
        }


    }

    //后置通知
    @AfterReturning(returning = "ret",pointcut = "weblog()")
    public void houzhi(String ret){
        //请求参数
        //logger.info ("Return:{}",ret);  //返回haha
    }

    //异常通知
    @AfterThrowing(throwing="ex",pointcut ="weblog()")
    public void afterThrowing(JoinPoint joinPoint, Exception ex) {

        String methodName = joinPoint.getSignature ().getName ();
        System.out.println ("异常方法: " + methodName + " : " + ex);

        ErrorLog errorLog = new ErrorLog ();
        errorLog.setErrorMethod (methodName);
        errorLog.setErrorMessage (ex.getMessage ());

        try {
            String uuid = StpUtil.getLoginIdAsString ();
            User user = userService.findUserNameByUUid (uuid);
            errorLog.setLoginName (user.getUsername ());
        } catch (NotLoginException e) {
            Object[] args = joinPoint.getArgs ();
            for (Object arg : args) {
                User user = Convert.convert (User.class, arg);
                errorLog.setLoginName (user.getUsername ());
            }
        }

        errorLogService.save(errorLog);
    }
}
